﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Collections;
using System.Data;
using Task.DB;
using Task.Log;
using System.Threading;
using System.Threading.Tasks;

namespace Task.Quartz.Execute.Holytax
{
    class VatReceiveEntity
    {
        #region

        public List<InvoiceResultEntity> InvoiceResultEntity { get; set; }

        public int CntAll { get; set; }

        public int CntInvalid { get; set; }

        public int CntAuthPass { get; set; }

        public int CntAuthNotPass { get; set; }

        public int CntNotNeedAuth { get; set; }
        public string strServerLongTime { get; set; }

        #endregion

        public VatReceiveEntity()
        {
            InvoiceResultEntity = new List<InvoiceResultEntity>();
        }

        #region

        public bool Analysis(string strXmlFileName, out string mess)
        {
            mess = string.Empty; 
            //return true;
            string errorSQL = string.Empty;
            try
            {
                var utility = FluentDB.ContextSQL();
                XmlDocument document = new XmlDocument();
                document.Load(strXmlFileName);

                //分删除、认证通过、认证未通过、无需认证处理
                XmlNodeList xnlInvalid = document.DocumentElement.SelectNodes("//row[yxbz=0 and inusr != '']");
                XmlNodeList xnlAuthPass = document.DocumentElement.SelectNodes("//row[yxbz=1 and (jg=00 or jg=01 or jg=03) and inusr != '']");
                XmlNodeList xnlAuthNotPass = document.DocumentElement.SelectNodes("//row[yxbz=1 and (jg=02 or jg=04) and inusr != '']");
                XmlNodeList xnlNotNeedAuth = document.DocumentElement.SelectNodes("//row[yxbz=1 and jg=09 and inusr != '']");

                string strServerLongTime = this.strServerLongTime;

                //获取将发票挪入删除表时使用的字段串
                string sbDelInsertFields = GetInvDelCol(utility);
                //获取将删除发票挪到备份表使用的列
                string sbBakInsertFields = GetInvBakCol(utility);

                List<string> arrTrans = new List<string>();

                int CntInvalidTemp = xnlInvalid == null ? 0 : xnlInvalid.Count;
                int xnlAuthPassTemp = xnlAuthPass == null ? 0 : xnlAuthPass.Count;
                int xnlAuthNotPassTemp = xnlAuthNotPass == null ? 0 : xnlAuthNotPass.Count;
                int xnlNotNeedAuthTemp = xnlNotNeedAuth == null ? 0 : xnlNotNeedAuth.Count;

                #region 无效票 (用户接受文件会出现文件处理失败） 删除 删除库中的 发票信息时应查看 物品信息删除表中是否有外键关联的数据，病将其删除。
                foreach (XmlNode node in xnlInvalid)
                {
                    arrTrans.Add(string.Format(@"
update inv_vat set hassent=2,deleteDate='{2}',receiveDate='{2}',receiveFileName='{3}' where invoicecode='{0}' and invoiceno='{1}' and buyer='{6}' and seller='{7}';
delete from inv_vatgoodsinfo_del where invoicePkid in (select pkid from inv_vat_del where invoicecode='{0}' and invoiceno='{1}');
DELETE FROM inv_vat_del WHERE invoicecode='{0}' and invoiceno='{1}';
insert into inv_vat_del({4}) select {4} from inv_vat where invoicecode='{0}' and invoiceno='{1}'and buyer='{6}' and seller='{7}';
insert into inv_vatgoodsinfo_del(pkid,invoicePkid,goodsname,goodsunit,goodsqty) select pkid,invoicePkid,goodsName,goodsUnit,goodsQty from inv_vatgoodsinfo where invoicePkid in(select pkid from inv_vat where invoicecode='{0}' and invoiceno='{1}');
delete from inv_vatgoodsinfo where invoicePkid in(select pkid from inv_vat where invoicecode='{0}' and invoiceno='{1}' and buyer='{6}' and seller='{7}');
delete from inv_vat where invoiceCode='{0}' and invoiceNo='{1}'  and buyer='{6}' and seller='{7}';
",

// if	(select COUNT(1) from INV_VAT_BAK where invoicecode='{0}' and invoiceno='{1}') <=0
                        //begin
                        //insert into INV_VAT_BAK ({5}) select {5} from INV_VAT_DEL  where invoicecode='{0}' and invoiceno='{1}'
                        //end
                node.SelectSingleNode("dm").InnerText,
                node.SelectSingleNode("hm").InnerText,
                strServerLongTime,
                strXmlFileName,
                sbDelInsertFields,
                sbBakInsertFields,
                node.SelectSingleNode("gf").InnerText,
                node.SelectSingleNode("xf").InnerText
                ));
                    InvoiceResultEntity.Add(new InvoiceResultEntity()
                    {
                        entTaxCode = node.SelectSingleNode("gf").InnerText,
                        invoicecode = node.SelectSingleNode("dm").InnerText,
                        invoiceno = node.SelectSingleNode("hm").InnerText,
                        authstatus = "删除票",
                    });
                }
                #endregion

                #region 认证通过票
                //
                //由于部分用户 有门店信息，而接收的XML文件中，不包含门店节点，因此，不对门店信息进行更新操作 删除字符串中 ,shopno='{13}'
                foreach (XmlNode node in xnlAuthPass)
                {
                    arrTrans.Add(string.Format(@"update inv_vat
set authstatus='{2}',authdate='{3}',errorcode='{4}',authdesc='{5}',statusId='{6}',
opentime='{7}',seller='{8}',amount='{9}',taxamount='{10}',taxpoint='{11}',
ciphertext='{12}',suppliercode='{14}',voucherno='{15}',
receivedate='{16}',receivefilename='{17}'
where invoicecode='{0}' and invoiceno='{1}' and statusId='03' and authStatus='01' and buyer='{18}' and seller='{19}'",
                    node.SelectSingleNode("dm").InnerText,
                    node.SelectSingleNode("hm").InnerText,
                    Eipp2Scan_AuthStatus(node.SelectSingleNode("jg").InnerText),
                    node.SelectSingleNode("rq").InnerText,
                    node.SelectSingleNode("cwdm").InnerText,
                    node.SelectSingleNode("rzsm").InnerText,
                    InvoiceSendStatus.Received,
                    node.SelectSingleNode("kr").InnerText,
                    node.SelectSingleNode("xf").InnerText,
                    node.SelectSingleNode("je").InnerText,
                    node.SelectSingleNode("se").InnerText,
                    node.SelectSingleNode("sl").InnerText.Replace(".0", "").Replace("0.", ""),
                    node.SelectSingleNode("mw").InnerText,
                    node.SelectSingleNode("fpmdh") != null ? node.SelectSingleNode("fpmdh").InnerText : "",
                    "",//node.SelectSingleNode("SUPPLIERCODE").InnerText,
                    node.SelectSingleNode("pzh") != null ? node.SelectSingleNode("pzh").InnerText : "",
                    strServerLongTime,
                    strXmlFileName,
                    node.SelectSingleNode("gf").InnerText,
                    node.SelectSingleNode("xf").InnerText));

                    InvoiceResultEntity.Add(new InvoiceResultEntity()
                    {
                        entTaxCode = node.SelectSingleNode("gf").InnerText,
                        invoicecode = node.SelectSingleNode("dm").InnerText,
                        invoiceno = node.SelectSingleNode("hm").InnerText,
                        authstatus = "认证通过",
                    });
                }
                #endregion

                #region 认证未通过票
                foreach (XmlNode node in xnlAuthNotPass)
                {
                    arrTrans.Add(string.Format(@"update inv_vat
set authstatus='{2}',authdate='{3}',errorcode='{4}',authdesc='{5}',statusId='{6}',
receivedate='{7}',receivefilename='{8}'
where invoicecode='{0}' and invoiceno='{1}' and statusId='03' and authStatus='01' and buyer='{9}' and seller='{10}'",
                    node.SelectSingleNode("dm").InnerText,
                    node.SelectSingleNode("hm").InnerText,
                    Eipp2Scan_AuthStatus(node.SelectSingleNode("jg").InnerText),
                    node.SelectSingleNode("rq").InnerText,
                    node.SelectSingleNode("cwdm").InnerText,
                    node.SelectSingleNode("rzsm").InnerText,
                    InvoiceSendStatus.Received,
                    strServerLongTime,
                    strXmlFileName,
                    node.SelectSingleNode("gf").InnerText,
                    node.SelectSingleNode("xf").InnerText));

                    InvoiceResultEntity.Add(new InvoiceResultEntity()
                    {
                        entTaxCode = node.SelectSingleNode("gf").InnerText,
                        invoicecode = node.SelectSingleNode("dm").InnerText,
                        invoiceno = node.SelectSingleNode("hm").InnerText,
                        authstatus = "认证未通过",
                    });
                }
                #endregion

                #region 无需认证票
                //
                //由于部分用户 有门店信息，而接收的XML文件中，不包含门店节点，因此，不对门店信息进行更新操作 删除字符串中 ,shopno='{13}'
                foreach (XmlNode node in xnlNotNeedAuth)
                {
                    arrTrans.Add(string.Format(@"update inv_vat
set authstatus='{2}',authdate='{3}',errorcode='{4}',authdesc='{5}',statusId='{6}',
opentime='{7}',seller='{8}',amount='{9}',taxamount='{10}',taxpoint='{11}',
ciphertext='{12}',suppliercode='{14}',voucherno='{15}',
receivedate='{16}',receivefilename='{17}'
where invoicecode='{0}' and invoiceno='{1}' and statusId='03' and authStatus='01' and buyer='{18}' and seller='{19}'",
                    node.SelectSingleNode("dm").InnerText,
                    node.SelectSingleNode("hm").InnerText,
                   Eipp2Scan_AuthStatus(node.SelectSingleNode("jg").InnerText),
                    node.SelectSingleNode("rq").InnerText,
                    node.SelectSingleNode("cwdm").InnerText,
                    node.SelectSingleNode("rzsm").InnerText,
                   InvoiceSendStatus.Received,
                    node.SelectSingleNode("kr").InnerText,
                    node.SelectSingleNode("xf").InnerText,
                    node.SelectSingleNode("je").InnerText,
                    node.SelectSingleNode("se").InnerText,
                    node.SelectSingleNode("sl").InnerText.Replace(".0", ""),
                    node.SelectSingleNode("mw").InnerText,
                     node.SelectSingleNode("fpmdh") != null ? node.SelectSingleNode("fpmdh").InnerText : "",
                    "",//node.SelectSingleNode("SUPPLIERCODE").InnerText,
                     node.SelectSingleNode("pzh") != null ? node.SelectSingleNode("pzh").InnerText : "",
                    strServerLongTime,
                    strXmlFileName,
                    node.SelectSingleNode("gf").InnerText,
                    node.SelectSingleNode("xf").InnerText));

                    InvoiceResultEntity.Add(new InvoiceResultEntity()
                    {
                        entTaxCode = node.SelectSingleNode("gf").InnerText,
                        invoicecode = node.SelectSingleNode("dm").InnerText,
                        invoiceno = node.SelectSingleNode("hm").InnerText,
                        authstatus = "无需认证",
                    });
                }
                #endregion

                CntAll = CntInvalidTemp + xnlAuthPassTemp + xnlAuthNotPassTemp + xnlNotNeedAuthTemp;
                CntInvalid = CntInvalidTemp;
                CntAuthPass = xnlAuthPassTemp;
                CntAuthNotPass = xnlAuthNotPassTemp;
                CntNotNeedAuth = xnlNotNeedAuthTemp;

                //分页处理,避免等待死锁与超时
                List<List<string>> listGroup = new List<List<string>>();
                List<string> cList = new List<string>();
                int pagesize = 10;
                for (int pageindex = 0; pageindex <= arrTrans.Count / pagesize; pageindex++)
                {
                    cList = new List<string>();
                    cList = arrTrans.Skip(pageindex * pagesize).Take(pagesize).ToList();
                    listGroup.Add(cList);
                }

                foreach (var item in listGroup)
                {
                    if (item.Count() <= 0)
                    {
                        continue;
                    }
                    //Parallel.ForEach(item, (itemSql) => utility.Sql(itemSql).Execute());
                    foreach (var itemSql in item)
                    {
                        utility.Sql(itemSql).Execute();
                    }
                    Thread.Sleep(500);
                }
                return true;
            }
            catch (Exception ex)
            {
                mess = ex.Message;
                LogHelper.Fatal(ex.ToString(), System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
                return false;
            }
        }

        public string Eipp2Scan_AuthStatus(string eippStr)
        {
            string scanStr = string.Empty;
            switch (eippStr)
            {
                case "00":
                    scanStr = AuthStatus.AuthPass;
                    break;
                case "02":
                    scanStr = AuthStatus.AuthNotPass;
                    break;
                case "09":
                    scanStr = AuthStatus.NotNeedAuth;
                    break;
            }
            return scanStr;
        }

        private string GetInvBakCol(FluentData.IDbContext utility)
        {
            List<string> list = new List<string>();
            DataTable dt = utility.Sql("select * from INV_VAT_BAK where 1 <> 1").QuerySingle<DataTable>();
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                list.Add(dt.Columns[i].ColumnName);
            }
            return string.Join(",", list.ToArray());
        }

        private string GetInvDelCol(FluentData.IDbContext utility)
        {
            List<string> list = new List<string>();
            DataTable dt = utility.Sql("select * from INV_VAT_DEL where 1 <> 1").QuerySingle<DataTable>();
            for (int i = 0; i < dt.Columns.Count; i++)
            {
                list.Add(dt.Columns[i].ColumnName);
            }
            return string.Join(",", list.ToArray());
        }

        private string GetNodeInnerText(XmlNode node)
        {
            if (node == null)
            {
                return string.Empty;
            }
            return node.InnerText;
        }
        #endregion
    }

    public class InvoiceResultEntity
    {
        public string entTaxCode { get; set; }
        public string invoicecode { get; set; }
        public string invoiceno { get; set; }
        public string authstatus { get; set; }
    }
    /// <summary>
    /// 认证状态
    /// </summary>
    public class AuthStatus
    {
        /// <summary>
        /// 初始
        /// </summary>
        public static readonly string Initial = "01";
        /// <summary>
        /// 认证通过
        /// </summary>
        public static readonly string AuthPass = "02";
        /// <summary>
        /// 认证未通过
        /// </summary>
        public static readonly string AuthNotPass = "03";
        /// <summary>
        /// 无需认证
        /// </summary>
        public static readonly string NotNeedAuth = "04";
    }

    /// <summary>
    /// 发票发送状态
    /// </summary>
    public class InvoiceSendStatus
    {
        /// <summary>
        /// 待补录
        /// </summary>
        public static readonly string WaitInput = "01";
        /// <summary>
        /// 待发送
        /// </summary>
        public static readonly string WaitSend = "02";
        /// <summary>
        /// 已发送未接收
        /// </summary>
        public static readonly string SentNotReceive = "03";
        /// <summary>
        /// 已接收
        /// </summary>
        public static readonly string Received = "04";
    }

    /// <summary>
    /// 密文类型
    /// </summary>
    public class CiphertextType
    {
        /// <summary>
        /// 普通密文
        /// </summary>
        public static readonly string Common = "01";
        /// <summary>
        /// 二维码密文
        /// </summary>
        public static readonly string TwoCode = "02";
    }
}
